//
//  GameState.m
//
//  Source file for the singleton GameState class which stores
//  settings such as music and sounds and data such as current
//  score and current level completed so far
//

#import "GameState.h"

@implementation GameState

// singleton
static GameState *_sharedGameState = nil;

// returns an instance of the singleton object
+(GameState *) sharedGameState
{
    if (!_sharedGameState) {
        [[self alloc] init];
    }
    
    return _sharedGameState;
}

+(id)alloc
{
    NSAssert(_sharedGameState == nil, @"Allocated extra game state object.");
    _sharedGameState = [super alloc];
    return _sharedGameState;
}

// set a particular state of the app
// these states persist even after closing the app
-(void)setState:(NSString *)state value:(id)stateValue
{
    // music and sound are booleans so must be handled differently
    if ([state isEqualToString:@"music"] || [state isEqualToString:@"sound"]) {
        [[NSUserDefaults standardUserDefaults] setBool:(stateValue ? YES : NO) forKey:state];
    }
    // same goes with these statistics values which have to be saved as integers
    else if ([state isEqualToString:@"totalTimePlayed"] || [state isEqualToString:@"totalScore"] || [state isEqualToString:@"totalGamesPlayed"] || [state isEqualToString:@"level1BestTime"] || [state isEqualToString:@"level2BestTime"] || [state isEqualToString:@"level3BestTime"]) {
        [[NSUserDefaults standardUserDefaults] setInteger:stateValue forKey:state];
    }
    else {
        [[NSUserDefaults standardUserDefaults] setObject:stateValue forKey:state];
    }
    
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(id)getState:(NSString *)state
{
    return [[NSUserDefaults standardUserDefaults] objectForKey:state];
}

-(int) getScore
{
    return _currentScore;
}

-(int) incScore
{
    return ++_currentScore;
}

-(int) decScore
{
    return --_currentScore;
}

-(void) resetScore
{
    _currentScore = 0;
}

-(int) getCompletion
{
    return _completedLevels;
}

-(void) saveHighestScore
{
    if (_currentScore != 0) {
        NSMutableDictionary *scoreDict = [[self getState:@"highscores"] mutableCopy];
        NSMutableArray *userScores = [[scoreDict objectForKey:_userName] mutableCopy];
        [userScores addObject:[NSNumber numberWithInt:_currentScore]];
        [scoreDict setObject:userScores forKey:_userName];
        [self setState:@"highscores" value:scoreDict];
    }
}

-(int) incCompletion
{
    return ++_completedLevels;
}

-(void) resetCompletion
{
    _completedLevels = 0;
}

-(NSString *) userName
{
    return _userName;
}

// erase all the current scores of the user
-(void) eraseScores
{    
    NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
    [settings setObject:[NSMutableDictionary dictionaryWithObject:[[NSMutableArray alloc] init] forKey:_userName] forKey:@"highscores"];
    [settings setInteger:0 forKey:@"totalTimePlayed"];
    [settings setInteger:0 forKey:@"totalScore"];
    [settings setInteger:0 forKey:@"totalGamesPlayed"];
    [settings setInteger:60 forKey:@"level1BestTime"];
    [settings setInteger:60 forKey:@"level2BestTime"];
    [settings setInteger:60 forKey:@"level3BestTime"];
    [settings synchronize];
}

// set the username of the current player and initialize
// user specific data such as highscores
-(void) setUserName:(NSString *)userName
{
    _userName = userName;
    
    NSMutableDictionary *scoreDict = [[self getState:@"highscores"] mutableCopy];
    
    NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
    
    //initialize empty scores
    if (scoreDict == nil) {
        [settings setObject:[NSMutableDictionary dictionaryWithObject:[[NSMutableArray alloc] init] forKey:userName] forKey:@"highscores"];
    }
    else {
        NSMutableArray *userScores = [scoreDict objectForKey:userName];
        if (userScores == nil) {
            [scoreDict setObject:[[NSMutableArray alloc] init] forKey:userName];
            [settings setObject:scoreDict forKey:@"highscores"];
        }
    }
    
    [settings synchronize];
}

-(void) sync
{
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(id)init
{
    self = [super init];
    if (self != nil) {
        _currentScore = 0;
        _completedLevels = 0;
        
        NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
        
        // initialize some of the settings to a default value if they
        // do not exist; this happens on the very first time the app is opened
        if ([settings objectForKey:@"music"] == nil) {
            [settings setBool:YES forKey:@"music"];
        }
        
        if ([settings objectForKey:@"sound"] == nil) {
            [settings setBool:YES forKey:@"sound"];
        }
        
        if ([settings objectForKey:@"totalTimePlayed"] == nil) {
            [settings setInteger:0 forKey:@"totalTimePlayed"];
        }
        
        if ([settings objectForKey:@"totalScore"] == nil) {
            [settings setInteger:0 forKey:@"totalScore"];
        }
        
        if ([settings objectForKey:@"totalGamesPlayed"] == nil) {
            [settings setInteger:0 forKey:@"totalGamesPlayed"];
        }
        
        if ([settings objectForKey:@"level1BestTime"] == nil) {
            [settings setInteger:60 forKey:@"level1BestTime"];
        }
        
        if ([settings objectForKey:@"level2BestTime"] == nil) {
            [settings setInteger:60 forKey:@"level2BestTime"];
        }
        
        if ([settings objectForKey:@"level3BestTime"] == nil) {
            [settings setInteger:60 forKey:@"level3BestTime"];
        }        
        
        [settings synchronize];
    }
    
    return self;
}

@end
